﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Rocket.Windows.Framework.Utilities;
using Rocket.Core;
using System.Linq.Expressions;

namespace Rocket.Windows.Framework
{
    /// <summary>
    /// The class that can be used to generalize the Grid View object.
    /// Parameter H : Handler Object
    /// Parameter V : Bussiness Object View
    /// </summary>
    /// <typeparam name="H"></typeparam>
    /// <typeparam name="V"></typeparam>
    public abstract partial class BaseGridView<H, V> : BaseControl, IFormGridView<V>
        where H : IHandler<V>
        where V : BaseObject
    {
        public event DataGridViewCellEventHandler DataRowSelected;
        public event DataGridViewCellEventHandler EndCellEdit;
        private H _hadler;  
        public BaseGridView(H h)
        {
            InitializeComponent();
            _hadler = h;
        }

        public Comparison<V> SortWith { get; set; }

        /// <summary>
        /// The method LoadData is used to Load All Purticular Entity Elements by
        /// calling Purticular Handler's GetAll() method.
        /// </summary>
        public virtual void LoadData()
        {
            List<V> list = _hadler.GetAll();
            if (SortWith != null)
                list.Sort(SortWith);
            this.DataList = list;
        }

        public virtual void LoadData<DTO>(Expression<Func<DTO, bool>> filterExpression)
            where DTO : class
        {
            List<V> list = null;
            if (filterExpression == null)
                list = _hadler.GetAll();
            else
                list = ((IHandler<V, DTO>)_hadler).GetAll(filterExpression);
            if (SortWith != null)
                list.Sort(SortWith);
            this.DataList = list;
        }

        private V _selectedItem;
        public V SelectedItem
        {
            get { return _selectedItem; }
        }

        private List<V> _originalList = null;
        private List<V> _dataList;
        public List<V> DataList
        {
            get { return _dataList; }
            set
            {
                _dataList = value;
                this.DataGridViewPlusMain.DataSource = null;
                if (_dataList == null) return;
                this.DataGridViewPlusMain.Columns.Clear();

                this.DataGridViewPlusMain.AutoGenerateColumns = true;
                this.DataGridViewPlusMain.DataSource = this._dataList;
                OnHideColumns(ref DataGridViewPlusMain);
                if (_dataList.Count > 0)
                {
                    int cCount = this.DataGridViewPlusMain.Columns.Count;
                    if (_dataList[0].Data != null)
                    {
                        foreach (KeyValuePair<string, object> item in _dataList[0].Data)
                        {
                            DataGridViewTextBoxColumn mRef = new DataGridViewTextBoxColumn();
                            mRef.HeaderText = item.Key;
                            this.DataGridViewPlusMain.Columns.Add(mRef);
                        }
                    }
                    for (int i = 0; i < DataGridViewPlusMain.RowCount; i++)
                    {
                        int c = cCount;
                        IObject boundItem = (V)DataGridViewPlusMain.Rows[i].DataBoundItem;
                        if (boundItem.Data != null)
                            foreach (KeyValuePair<string, object> item in boundItem.Data)
                                this.DataGridViewPlusMain[c++, i].Value = item.Value;
                    }
                }
            }
        }

        private bool _loadWhenStart = true;
        public bool LoadWhenStart
        {
            get { return _loadWhenStart; }
            set { _loadWhenStart = value; }
        }

        public bool HideSearchOption
        {
            get { return !this.panel1.Visible; }
            set { this.panel1.Visible = !value; }
        }

        protected virtual void OnHideColumns(ref DataGridViewPlus<V> DataGridViewPlus)
        {
            //DataGridViewPlus.Columns["Id"].Visible = false;
            //DataGridViewPlus.Columns["Data"].Visible = false;
            //DataGridViewPlus.Columns["SourcePoco"].Visible = false;
        }

        public string GroupBoxName
        {
            get { return groupBoxMain.Text; }
            set { groupBoxMain.Text = value; }
        }

        /// <summary>
        /// The Generic Search method used for search elements in Purticular Entity set.
        /// You can use this functionality in User Interface for search any elements which are
        /// display in grid. 
        /// Ex : 
        /// Search by,
        ///     Id, Name, Description etc.
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        protected List<V> Search(string query)
        {
            if (_dataList == null) return null;
            List<V> list = new List<V>();
            string[] qItems = query.Split(' ');
            foreach (V item in _dataList)
            {
                for (int i = 0; i < qItems.Length; i++)
                    if (item.FoundIt(qItems[i]))
                        list.Add(item);
            }
            return (list.Count > 0) ? list : null;
        }

        private void buttonSearch_Click(object sender, EventArgs e)
        {
            if (_originalList == null)
            {
                _originalList = _dataList;
                return;
            }

            string s = this.textBoxSearch.Text.Trim();
            this.DataGridViewPlusMain.Columns.Clear();
            if (string.IsNullOrEmpty(s))
                this.DataList = _originalList;
            else
                this.DataList = this.Search(s);
        }

        private void DataGridViewPlusMain_RowEnter(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
                _selectedItem = (V)DataGridViewPlusMain.Rows[e.RowIndex].DataBoundItem;

            if (DataRowSelected != null)
                DataRowSelected(_selectedItem, e);
        }

        void DataGridViewPlusMain_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (EndCellEdit != null)
                EndCellEdit(sender, e);
        }

        private void buttonRefresh_Click(object sender, EventArgs e)
        {
            LoadData();
            this.textBoxSearch.Text = "";
        }
    }
}
